package be.fedict.eid.viewer;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

import javax.smartcardio.Card;
import javax.smartcardio.CardTerminal;

import be.fedict.commons.eid.client.BeIDCard;
import be.fedict.commons.eid.client.BeIDCardManager;
import be.fedict.commons.eid.client.CardAndTerminalManager;
import be.fedict.commons.eid.client.event.BeIDCardEventsListener;
import be.fedict.commons.eid.client.event.CardEventsListener;
import be.fedict.commons.eid.client.event.CardTerminalEventsListener;
import be.fedict.commons.eid.client.spi.Logger;

/**
 * @author frank
 * 
 */
public class Viewer implements BeIDCardEventsListener, CardEventsListener,
	CardTerminalEventsListener {
    private Map<CardTerminal, CardTerminalManager> terminalManagers;

    public Viewer() {
	super();
	this.terminalManagers = new HashMap<CardTerminal, CardTerminalManager>();
    }

    private void run() {
	final CardAndTerminalManager cardAndTerminalManager = new CardAndTerminalManager(new Logger()
	{

	    @Override
	    public void error(String message) {
		System.err.println(message);
		
	    }

	    @Override
	    public void debug(String message) {
		System.err.println(message);
		
	    }
	    
	});
	final BeIDCardManager beIDCardManager = new BeIDCardManager(
		cardAndTerminalManager);
	beIDCardManager.addBeIDCardEventListener(this);
	beIDCardManager.addOtherCardEventListener(this);
	cardAndTerminalManager.addCardTerminalListener(this);
	beIDCardManager.start();
	cardAndTerminalManager.start();

	for (;;) {
	    try {
		Thread.sleep(2000);
	    } catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	}
    }

    // -----------------------------------------

    public static void main(String[] args) {
	new Viewer().run();
    }

    // ------------------------------------------------------------------------------------------------------------
    // these respond to CardTerminals being attached and detached
    // ------------------------------------------------------------------------------------------------------------

    @Override
    public void terminalAttached(final CardTerminal cardTerminal) {
	System.out.println("CardTerminal [" + cardTerminal.getName()
		+ "] attached\n");
	CardTerminalManager cardTerminalManager = new CardTerminalManager(
		cardTerminal);
	terminalManagers.put(cardTerminal, cardTerminalManager);
    }

    @Override
    public void terminalDetached(final CardTerminal cardTerminal) {
	System.out.println("CardTerminal [" + cardTerminal.getName()
		+ "] detached\n");
	terminalManagers.remove(cardTerminal);
    }

    @Override
    public void terminalEventsInitialized() {
    }

    // ------------------------------------------------------------------------------------------------------------
    // these respond to BeID cards being inserted and removed
    // ------------------------------------------------------------------------------------------------------------

    @Override
    public void eIDCardInserted(final CardTerminal cardTerminal,
	    final BeIDCard card) {
	System.out.println("BeID Card Inserted Into Card Termimal ["
		+ cardTerminal.getName() + "]\n");
	CardTerminalManager cardTerminalManager = terminalManagers
		.get(cardTerminal);
	if (cardTerminalManager != null) {
	    cardTerminalManager.eIDCardInserted(card);
	}
    }

    @Override
    public void eIDCardRemoved(final CardTerminal cardTerminal,
	    final BeIDCard card) {
	System.out.println("BeID Card Removed From Card Termimal ["
		+ cardTerminal.getName() + "]\n");
	CardTerminalManager cardTerminalManager = terminalManagers
		.get(cardTerminal);
	if (cardTerminalManager != null) {
	    cardTerminalManager.eIDCardRemoved(card);
	}
    }

    @Override
    public void eIDCardEventsInitialized() {
    }

    // ------------------------------------------------------------------------------------------------------------
    // these respond to non-BeID cards being inserted and removed
    // (because we registered with a BeIDCardManager, not a
    // CardAndTerminalManager)
    // ------------------------------------------------------------------------------------------------------------

    @Override
    public void cardInserted(final CardTerminal cardTerminal, final Card card) {
	if (card != null) {
	    System.out.println("Other Card ["
		    + String.format("%x", new BigInteger(1, card.getATR()
			    .getBytes())) + "] Inserted Into Terminal ["
		    + cardTerminal.getName() + "]");
	    CardTerminalManager cardTerminalManager = terminalManagers
		    .get(cardTerminal);
	    if (cardTerminalManager != null) {
		cardTerminalManager.otherCardInserted(card);
	    }
	} else {
	    System.out.println("Other Card Inserted Into Terminal ["
		    + cardTerminal.getName() + "] but failed to connect()");
	}
    }

    @Override
    public void cardRemoved(final CardTerminal cardTerminal) {
	System.out.println("Other Card Removed From [" + cardTerminal.getName()
		+ "]");
	CardTerminalManager cardTerminalManager = terminalManagers
		.get(cardTerminal);
	if (cardTerminalManager != null) {
	    cardTerminalManager.otherCardRemoved();
	}
    }

    @Override
    public void cardEventsInitialized() {
    }

}
